package cz.pecinovsky.česky.oopnz._000_;

import cz.pecinovsky.česky.oopnz.utility.IO;
import cz.pecinovsky.česky.oopnz.tvary.Plátno;

import java.lang.reflect.Constructor;

import junit.framework.TestCase;
import junit.framework.TestResult;
import junit.textui.TestRunner;



/*******************************************************************************
 * Třída {@code Run} je knihovní třídou poskytují metodu {@code tests},
 * která provede všechny testy, jejichž názvy obdrží v paramtrech.
 * Slouží k tomu, aby se v průběhu vývoje dalo co nejsnadněji definovat,
 * které testy se budou a nebudou spouštět - stačí jenom zakomentovat řádky
 * s názvy nespouštěných testů.
 * <p>
 * Abychom se nemuseli při zakomentovávání naprováděných testů zabývat tím,
 * zda právě nezakomntováváme poslední test, z aním (na rozdíl od ostatních)
 * již není čárka, můžeme zako poslední název zadat prázdný řetězec,
 * který pak bude metoda ignorovat.
 *
 * @author Rudolf PECINOVSKÝ
 * @version 6.03.2017 — 2010-11-08
 */
public class Run
{
//== KONSTANTNÍ ATRIBUTY TŘÍDY =================================================
//== PROMĚNNÉ ATRIBUTY TŘÍDY ===================================================
//== STATICKÝ INICIALIZAČNÍ BLOK - STATICKÝ KONSTRUKTOR ========================
//== KONSTANTNÍ ATRIBUTY INSTANCÍ ==============================================
//== PROMĚNNÉ ATRIBUTY INSTANCÍ ================================================
//== PŘÍSTUPOVÉ METODY VLASTNOSTÍ TŘÍDY ========================================
//== OSTATNÍ NESOUKROMÉ METODY TŘÍDY ===========================================

    /***************************************************************************
     * Postupně spustí každý ze zadaných testů přičemž po jeho skončení
     * toto oznámí v dialogovém okně a uklidí po něm plátno.
     * Slouží k tomu, aby se v průběhu vývoje dalo co nejsnadněji definovat,
     * které testy se budou a nebudou spouštět - stačí jenom zakomentovat řádky
     * s názvy nespouštěných testů.
     * <p>
     * Abychom se nemuseli při zakomentovávání naprováděných testů zabývat tím,
     * zda právě nezakomntováváme poslední test, z aním (na rozdíl od ostatních)
     * již není čárka, můžeme zako poslední název zadat prázdný řetězec,
     * který pak bude metoda ignorovat. <b>Obecně metoda ignoruje všechny názvy
     * následující za případným prázdným řetězcem.</b>
     *
     * @param třída       Testovací třída, jejíž testu budeme spouštět
     * @param td          Instance mající na strosti úklid mezi testy
     * @param názvyTestů  Názvy spouštěných testů
     */
    public static void tests(Class<? extends TestCase> třída,
                             ITD td,
                             String... názvyTestů)
    {
        Constructor<? extends TestCase> konstruktor;
        try {
            konstruktor = třída.getConstructor(String.class);
        }catch(Exception ex) {
            throw new RuntimeException(
                "\nNepodařilo se vytvořit \"stringový\" konstruktor třídy: " +
                třída.getName(), ex);
        }
        for (String název : názvyTestů) {
            if (název.equals("")) {
                return;
            }
            TestCase test;
            try {
                test = konstruktor.newInstance(název);
            } catch (Exception ex) {
                throw new RuntimeException(
                    "\nNepodařilose vytvořit instanci testu: " + název, ex);
            }
            TestResult result = TestRunner.run(test);
            if (result.wasSuccessful()) {
                IO.zpráva(název);
            }
            else {
                IO.zpráva(test + "\n\nTest se nezdařil");
            }
            td.ukliď();
        }

    }

//##############################################################################
//== KONSTRUKTORY A TOVÁRNÍ METODY =============================================

    /***************************************************************************
     *
     */
    private Run()
    {
    }


//== ABSTRAKTNÍ METODY =========================================================
//== PŘÍSTUPOVÉ METODY VLASTNOSTÍ INSTANCÍ =====================================
//== OSTATNÍ NESOUKROMÉ METODY INSTANCÍ ========================================
//== SOUKROMÉ A POMOCNÉ METODY TŘÍDY ===========================================
//== SOUKROMÉ A POMOCNÉ METODY INSTANCÍ ========================================
//== INTERNÍ DATOVÉ TYPY =======================================================

    /***************************************************************************
     * Instance třídy {@code Run.TD} (TD od {@code tearDown})
     * zabezpěčí úklid mezi testy, který není možno zakomponovat do metody
     * {@code tearDown()}, dokud nebudou studenti umět programovat.
     */
    public static interface ITD
    {
        /***********************************************************************
         * Uklidí po testu tak, aby mohl ihned odstartovat další test.
         */
        public void ukliď();
    }



//== TESTY A METODA MAIN =======================================================
//
//    /***************************************************************************
//     * Testovací metoda.
//     */
//    public static void test()
//    {
//        SpuštěníTestů inst = new SpuštěníTestů();
//    }
//    /** @param args Parametry příkazového řádku - nepoužívané. */
//    public static void main( String[] args )  {  test();  }
}
